package envelopes

import (
	"context"
	"gitee.com/wm1998/infra/base"
	"gitee.com/wm1998/resk/services"
	"github.com/segmentio/ksuid"
	"github.com/tietang/dbx"
)

// 收/抢红包-红包/商品详情-业务领域层结构体
type itemDomain struct {
	RedEnvelopeItem // 包含了订单商品详情PO结构体
}

// 生成红包商品/订单详情编号
func (d *itemDomain) createItemNo() {
	d.ItemNo = ksuid.New().Next().String()
}

// 根据红包商品/订单详情DTO，创建红包商品/订单详情
func (d *itemDomain) Create(item services.RedEnvelopeItemDTO) {
	d.RedEnvelopeItem.FromDTO(&item)
	// 因为订单商品详情PO结构体的RecvUsername字段其约束可以为null，所以设置为true代表该字符值不为NULL
	d.RecvUsername.Valid = true
	d.createItemNo()
}

// 持久化红包商品/订单详情-即为收/抢红包，返回插入新数据返回的主键id
func (d *itemDomain) Save(ctx context.Context) (id int64, err error) {
	err = base.ExecuteContext(ctx, func(runner *dbx.TxRunner) error {
		dao := RedEnvelopeItemDao{runner: runner}
		id, err = dao.Insert(&d.RedEnvelopeItem)
		return err
	})
	return id, err
}

// 根据上下文、红包/订单详情编号，查询抢到的红包详情DTO
func (d *itemDomain) GetOne(ctx context.Context, itemNo string) (dto *services.RedEnvelopeItemDTO) {
	err := base.Tx(func(runner *dbx.TxRunner) error {
		dao := RedEnvelopeItemDao{runner: runner}
		po := dao.GetOne(itemNo)
		if po != nil {
			dto = po.ToDTO()
		}
		return nil
	})
	if err != nil {
		return nil
	}
	return dto
}

// 根据用户ID、红包编号，查询抢到的红包商品/订单详情DTO
func (d *itemDomain) GetByUser(userId, envelopeNo string) (dto *services.RedEnvelopeItemDTO) {
	err := base.Tx(func(runner *dbx.TxRunner) error {
		dao := RedEnvelopeItemDao{runner: runner}
		po := dao.GetByUser(envelopeNo, userId)
		if po != nil {
			dto = po.ToDTO()
		}
		return nil
	})
	if err != nil {
		return nil
	}
	return dto
}

// 根据红包编号，查询已抢到红包商品/订单详情列表（DTO的切片）
func (d *itemDomain) FindItems(envelopeNo string) (itemDtos []*services.RedEnvelopeItemDTO) {
	var items []*RedEnvelopeItem
	err := base.Tx(func(runner *dbx.TxRunner) error {
		dao := RedEnvelopeItemDao{runner: runner}
		items = dao.FindItems(envelopeNo)
		return nil
	})

	if err != nil {
		return itemDtos
	}
	itemDtos = make([]*services.RedEnvelopeItemDTO, 0)
	if len(items) == 0 {
		return itemDtos
	}
	var luckItem *services.RedEnvelopeItemDTO
	for i, po := range items {
		item := po.ToDTO()

		if i == 0 {
			luckItem = item
		} else {
			if luckItem.Amount.Cmp(po.Amount) < 0 {
				luckItem = item
			}
		}
		itemDtos = append(itemDtos, item)
	}
	//luckItem.IsLuckiest = true
	return itemDtos
}
